#include "imageview.h"
#include <QResizeEvent>
#include <QPainter>
#include <QFileInfo>
#include "imageloader.h"

ImageView::ImageView(QWidget *parent) :
    QWidget(parent), m_infotype(NoInfo), m_core(NULL), m_thread(this), m_stop(false)
{
    connect(this, SIGNAL(loaded(QImage)), this, SLOT(frame(QImage)), Qt::QueuedConnection);
    //connect(&m_loader, SIGNAL(frame(QImage)), this, SLOT(frame(QImage)));
    m_color1 = palette().color(QPalette::Highlight);// QColor(180, 200, 255);
    //m_color1.setAlpha(192);
    m_color2 = QColor(30, 30, 30, 0);
    m_color3 = palette().color(QPalette::Text);
    m_font1.setPointSize(16);
    m_check = QPixmap::fromImage(QImage(":/images/check.png").scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));

    m_thread.start();
}

ImageView::~ImageView()
{
    m_mutex.lock();
    m_stop = true;
    m_cond.wakeAll();
    m_mutex.unlock();
    m_thread.wait();
}

void ImageView::setCore(PioCore * core)
{
    m_core = core;
    connect(m_core, SIGNAL(updated(MediaItemPtr)), this, SLOT(onUpdate(MediaItemPtr)));
}

void ImageView::onUpdate(MediaItemPtr item)
{
    if(m_item == item)
        update();
}

void ImageView::onRemove(MediaItemPtr item)
{
    if(m_item == item)
        emit next();
}

void ImageView::load(MediaItemPtr item)
{
    m_item = item;
    QFileInfo fi(item->metadata().filename);
    m_title = (item->metadata().collection.isEmpty() ? tr("my collection") : item->metadata().collection) + "  \xbb  " + fi.baseName() + "." + fi.completeSuffix();
    m_info1 = item->metadata().created.toString();
    m_info2 = exifinfo(item->metadata().filename).join("     \xb7     ");

    m_mutex.lock();
    m_filename = item->metadata().filename;
    m_cond.wakeAll();
    m_mutex.unlock();
    //m_loader.load(item);
}

void ImageView::frame(const QImage &image)
{
    m_image = image;
    repaint();
}

void ImageView::clear()
{
    m_mutex.lock();
    m_filename = QString();
    m_cond.wakeAll();
    m_mutex.unlock();
    //m_loader.clear();
}

void ImageView::addOverlay(QWidget *widget)
{
    m_overlays.append(widget);
    widget->setParent(this);
    widget->resize(size());
    widget->show();
}

void ImageView::removeOverlay(QWidget *widget)
{
    m_overlays.removeAll(widget);
    widget->setParent(NULL);
}

void ImageView::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.fillRect(0, 0, width(), height(), Qt::BackgroundRole);
    if(m_image.isNull())
        return;

    int w = m_image.width();
    int h = m_image.height();
    int x = (width() - w)/2;
    int y = (height() - h)/2;
    p.drawImage(x, y, m_image);

    int margin = 10;
    int spacing = 5;

    if(m_infotype != NoInfo) {
        QLinearGradient gradient(0, 0, width(), 0);
        gradient.setColorAt(0, m_color1);
        gradient.setColorAt(1, m_color2);
        QBrush brush(gradient);

        QRect r(x, y + h - 100, w, 80);

        p.fillRect(r, brush);

        p.setBrush(m_color3);

        r.adjust(margin, margin, -margin, -margin);
        QRect br;
        p.setFont(m_font1);
        p.drawText(r, Qt::AlignLeft | Qt::AlignTop, m_title, &br);
        r.adjust(0, br.height() + spacing, 0, 0);
        if(m_infotype >= InfoDate) {
            p.setFont(m_font2);
            p.drawText(r, Qt::AlignLeft | Qt::AlignTop, m_info1, &br);
            r.adjust(0, br.height() + spacing, 0, 0);
            if(m_infotype >= InfoExif) {
                p.setFont(m_font2);
                p.drawText(r, Qt::AlignLeft | Qt::AlignTop, m_info2, &br);
            }
        }

        if(m_item->isSelected()) {
            QImage pm(":/images/check.png");
            p.drawImage(x + w - pm.width() - margin, y + h - 60 - pm.height() / 2, pm);
        }
    }

    if(m_item->isChecked())
        p.drawPixmap(width() - 2 * m_check.width(), height() - 2 * m_check.height(), m_check);
}

void ImageView::resizeEvent(QResizeEvent * e)
{
    m_mutex.lock();
    m_size = e->size();
    m_cond.wakeAll();
    m_mutex.unlock();

    //m_loader.setSize(e->size());
    foreach(QWidget * w, m_overlays) {
        w->resize(e->size());
    }
}

void ImageView::mouseDoubleClickEvent(QMouseEvent *)
{
    emit closeImage();
}

void ImageView::wheelEvent(QWheelEvent * e)
{
    if(e->delta() > 0)
        emit prev();
    else if(e->delta() < 0)
        emit next();
}

void ImageView::keyPressEvent(QKeyEvent * e)
{
    if(e->key() == Qt::Key_Left) {
        emit prev();
        e->accept();
    }
    else if(e->key() == Qt::Key_Right) {
        emit next();
        e->accept();
    }
    else if(e->key() == Qt::Key_Escape || e->key() == Qt::Key_Return) {
        emit closeImage();
        e->accept();
    }
    else if(e->key() == Qt::Key_I) {
        if(m_infotype == NoInfo)
            m_infotype = InfoExif;
        else
            m_infotype = NoInfo;
        //m_infotype = (m_infotype + 1) % InfoMax;
        repaint();
    }
    else if(e->key() == Qt::Key_Space) {
        if(m_item != NULL)
            m_core->select(m_item, !m_item->isSelected());
        m_infotype = InfoExif;
        repaint();
    }
    else
        QWidget::keyPressEvent(e);
}

QStringList ImageView::exifinfo(QString filename)
{
    QStringList infos;

/*    ExifLoader * loader = exif_loader_new();
    exif_loader_ref(loader);

    exif_loader_write_file(loader, filename.toLocal8Bit().data());
    ExifData * data = exif_loader_get_data(loader);
    if(data) {
        char buf[1024];
        ExifEntry * entry;
        if((entry = exif_content_get_entry(data->ifd[EXIF_IFD_EXIF], EXIF_TAG_FNUMBER)) != NULL) {
            infos << QString(exif_entry_get_value(entry, buf, sizeof(buf)));
        }
        if((entry = exif_content_get_entry(data->ifd[EXIF_IFD_EXIF], EXIF_TAG_EXPOSURE_TIME)) != NULL) {
            infos << QString(exif_entry_get_value(entry, buf, sizeof(buf)));
        }
        if((entry = exif_content_get_entry(data->ifd[EXIF_IFD_EXIF], EXIF_TAG_ISO_SPEED_RATINGS)) != NULL) {
            infos << tr("ISO ") + QString(exif_entry_get_value(entry, buf, sizeof(buf)));
        }
        if((entry = exif_content_get_entry(data->ifd[EXIF_IFD_EXIF], EXIF_TAG_FOCAL_LENGTH)) != NULL) {
            infos << QString(exif_entry_get_value(entry, buf, sizeof(buf)));
        }
        exif_data_unref(data);
    }
    exif_loader_unref(loader);*/

    return infos;
}

void ImageView::run()
{
    QString filename;
    QSize size;
    ImageLoader loader;
    m_mutex.lock();
    while(!m_stop) {
        if(filename != m_filename || size != m_size) {
            filename = m_filename;
            size = m_size;
            m_mutex.unlock();

            QImage image = loader.load(filename, size);
            emit loaded(image);

            m_mutex.lock();
            continue;
        }

        m_cond.wait(&m_mutex);
    }
    m_mutex.unlock();
}
